package com.huanxing.cloud.common.myabtis.datascope;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.huanxing.cloud.common.core.constant.CommonConstants;
import com.huanxing.cloud.common.myabtis.properties.ShopConfigProperties;
import com.huanxing.cloud.common.security.entity.HxUser;
import com.huanxing.cloud.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;

/**
 * 店铺数据权限处理器
 *
 * @author lijx
 * @date 2024/05/07 15:03
 */
@RequiredArgsConstructor
public class ShopDataPermissionInterceptor implements InnerInterceptor {

	private final ShopConfigProperties shopConfigProperties;

	@Override
	public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
			ResultHandler resultHandler, BoundSql boundSql) {
		// 这里可以进行一些查询前的处理
		PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
		String originalSql = boundSql.getSql();

		String mapperName = findStatementMappedClassName(ms);

		String methodName = findMethodName(ms.getId());
		// 这里可以根据自己的需求配置需要拦截的mapper方法
		if (!StrUtil.containsAny(methodName, "selectList", "selectOne", "selectMaps", "selectPage", "selectCount",
				"selectAdminPage")) {
			return;
		}
		// 判断是否需要进行数据权限处理
		List<String> mapperList = shopConfigProperties.getMappers();
		if (CollectionUtils.isEmpty(mapperList)) {
			return;
		}
		if (!mapperList.contains(mapperName)) {
			return;
		}

		HxUser hxUser = SecurityUtils.getUser();
		if (Objects.isNull(hxUser)) {
			return;
		}

		// 判断是否是店铺类型用户
		String type = hxUser.getType();
		if (!StringUtils.hasText(type)) {
			return;
		}

		if (!CommonConstants.YES.equals(type)) {
			return;
		}
		String shopId = hxUser.getShopId();
		if (!StringUtils.hasText(shopId)) {
			return;
		}

		// selectCount查询需要单独处理sql
		if (ms.getId().contains("selectCount")) {
			originalSql = String.format("%s %s shop_id = '%s'", originalSql,
					StrUtil.containsAnyIgnoreCase(originalSql, "where") ? "AND" : "WHERE", shopId);
		}
		else {
			originalSql = String.format("SELECT * FROM (%s) temp_data_scope WHERE temp_data_scope.%s = '%s'",
					originalSql, "shop_id", shopId);
		}
		mpBoundSql.sql(originalSql);
	}

	private String findMethodName(String id) {
		// 使用lastIndexOf找到方法名开始的位置，并使用substring提取方法名
		int lastIndexOfDot = id.lastIndexOf('.');
		if (lastIndexOfDot == -1) {
			return "";
		}
		return id.substring(lastIndexOfDot + 1);
	}

	private String findStatementMappedClassName(MappedStatement ms) {
		String msId = ms.getId();
		int lastIndexOfDot = msId.lastIndexOf('.');
		if (lastIndexOfDot == -1) {
			return "";

		}
		String className = msId.substring(0, lastIndexOfDot);
		int lastIndexOfMapper = className.lastIndexOf('.');
		if (lastIndexOfMapper == -1) {
			return "";
		}
		return className.substring(lastIndexOfMapper + 1);
	}

}
